package com.chushouya.manager.service.api.impl;

import cn.hutool.core.util.StrUtil;
import com.chushouya.common.util.IpUtils;
import com.chushouya.common.util.LbsUtil;
import com.general.framework.core.exception.Ex;
import com.general.framework.core.lang.Jsons;
import com.general.framework.core.lang.Strings;
import com.chushouya.manager.dao.entity.RegionEntity;
import com.chushouya.manager.dao.repository.RegionRepository;
import com.chushouya.manager.dto.admin.region.RegionQuery;
import com.chushouya.manager.dto.api.geocoder.GeoLocationDTO;
import com.chushouya.manager.dto.api.geocoder.LocationDTO;
import com.chushouya.manager.service.api.GeocoderApiService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Map;
import java.util.Objects;

@Service
@Slf4j
public class GeocoderApiServiceImpl implements GeocoderApiService {


    @Value("${com.tencent.lbs.key}")
    private String lbsKey;

    @Resource
    private RegionRepository regionRepository;

    @Override
    public GeoLocationDTO geoLocation(HttpServletRequest request, String ip, String lat, String lng) {
        String realIp = IpUtils.getIpAddr(request);
        if (realIp.contains(",")) {
            realIp = realIp.split(",")[0];
        }
        // 判断是否为局域网IP，如果是则返回空
        if (IpUtils.internalIp(realIp)) {
            return null;
        }
        if(Strings.isBlank(ip)){
            ip = realIp;
        }
        Map<String, String> geoMap;
        if (Objects.equals("-1", lat) || Objects.equals("-1", lng)) {
            lat = "";
            lng = "";
        }
        if (Strings.isNotBlank(lat) && Strings.isNotBlank(lng)) {
            //经纬度查询
            geoMap = LbsUtil.geocoder(lbsKey, lat, lng);
        } else if (Strings.isNotBlank(ip)) {
            //ip查询
            geoMap = LbsUtil.locationIp(lbsKey, ip);
        } else {
            log.debug("geoLocation:ip={},lat={},lng={},geoMap={}", ip, lat, lng, null);
            return null;
        }
        if (Objects.isNull(geoMap)) {
            // throw Ex.business("定位失败，请检查网络连接或API配置。");
            return null;
        }
        log.debug("geoLocation:ip={},lat={},lng={},geoMap={}", ip, lat, lng, geoMap);
        return buildGeoLocation(geoMap);
    }

    @Override
    public GeoLocationDTO ipLocation(HttpServletRequest request) {
        String ip = IpUtils.getIpAddr(request);
        if (ip.contains(",")) {
            ip = ip.split(",")[0];
        }
        if (IpUtils.internalIp(ip)) {
            return null;
        }
        log.info("ipLocation:ip={}", ip);
        Map<String, String> geoMap = LbsUtil.locationIp(lbsKey, ip);
        try {
            final String lat = geoMap.get("lat");
            final String lng = geoMap.get("lng");
            return geoLocation(request, ip, lat, lng);
        } catch (Exception e) {
            log.error("ip定位失败", e.getMessage());
            throw Ex.business("定位失败,请检查网络连接或API配置");
        }
    }

    @Override
    public String ipAddress(HttpServletRequest request) {
        final String realIp = IpUtils.getIpAddr(request);
        return realIp;
    }

    @Override
    public LocationDTO locationGeocoder(String address) {
        Map<String, String> geoMap = LbsUtil.locationGeocoder(address, lbsKey);
        return Jsons.parseObject(Jsons.toJsonString(geoMap), LocationDTO.class);
    }

    /**
     * 构建地理位置
     */
    private GeoLocationDTO buildGeoLocation(Map<String, String> geoMap) {
        String areaCode = geoMap.get("adCode");
        if (Strings.isBlank(areaCode)) {
            log.error("定位失败，未获取到区域编码 {}", Jsons.toJsonString(geoMap));
            throw Ex.business("定位失败，请检查网络连接或API配置");
        }
        if (Objects.equals("441900", areaCode)) {
            areaCode = "441999";
        }
        Long districtCode = Long.valueOf(areaCode);
        RegionQuery regionQuery = new RegionQuery();
        regionQuery.setDistrictCode(districtCode);

        RegionEntity regionEntity = regionRepository.selectOne(regionQuery);

        if(Objects.isNull(regionEntity)){
            throw Ex.business("未匹配到省市区 {}", areaCode);
        }
        String address = StrUtil.nullToEmpty(geoMap.get("address"));
        //判断是否为纯数字
        if (address.matches("[0-9]+")) {
            address = "";
        }
        //查询城市
        GeoLocationDTO dto = new GeoLocationDTO();
        dto.setProvince(regionEntity.getProvince());
        dto.setCity(regionEntity.getCity());
        dto.setDistrict(regionEntity.getDistrict());
        dto.setAddress(address);
        dto.setAdCode(areaCode);
        dto.setProvinceCode(regionEntity.getProvinceCode().toString());
        dto.setCityCode(regionEntity.getCityCode().toString());
        return dto;
    }
}
